home *** CD-ROM | disk | FTP | other *** search
/ Cre@te Online 2000 December / Cre@teOnline CD05.iso / MacSoft / XML ConsoleMax.sea / XML ConsoleMax / Required / esc.jar / com / extensibility / rock / GifEncoder.class (.txt) < prev    next >
Encoding:
Java Class File  |  2000-06-30  |  7.1 KB  |  405 lines

  1. package com.extensibility.rock;
  2.  
  3. import java.awt.Image;
  4. import java.awt.image.ImageProducer;
  5. import java.io.IOException;
  6. import java.io.OutputStream;
  7. import java.util.Hashtable;
  8.  
  9. public class GifEncoder extends ImageEncoder {
  10.    private boolean interlace = false;
  11.    int width;
  12.    int height;
  13.    byte[][] rgbPixels;
  14.    private final int HASH_PRIME;
  15.    private int colorsUsed = 0;
  16.    GifEncoderHashitem[] hashArray = new GifEncoderHashitem[509];
  17.    Hashtable colorHash;
  18.    int Width;
  19.    int Height;
  20.    boolean Interlace;
  21.    int curx;
  22.    int cury;
  23.    int CountDown;
  24.    int Pass = 0;
  25.    static final int EOF = -1;
  26.    static final int BITS = 12;
  27.    static final int HSIZE = 5003;
  28.    int n_bits;
  29.    int maxbits = 12;
  30.    int maxcode;
  31.    int maxmaxcode = 4096;
  32.    int[] htab = new int[5003];
  33.    int[] codetab = new int[5003];
  34.    int hsize = 5003;
  35.    int free_ent = 0;
  36.    boolean clear_flg = false;
  37.    int g_init_bits;
  38.    int ClearCode;
  39.    int EOFCode;
  40.    int cur_accum = 0;
  41.    int cur_bits = 0;
  42.    int[] masks = new int[]{0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535};
  43.    int a_count;
  44.    byte[] accum = new byte[256];
  45.  
  46.    public GifEncoder(Image var1, OutputStream var2) throws IOException {
  47.       super(var1, var2);
  48.       super.allowAccumulate = false;
  49.    }
  50.  
  51.    public GifEncoder(Image var1, OutputStream var2, boolean var3) throws IOException {
  52.       super(var1, var2);
  53.       this.interlace = var3;
  54.       super.allowAccumulate = false;
  55.    }
  56.  
  57.    public GifEncoder(ImageProducer var1, OutputStream var2) throws IOException {
  58.       super(var1, var2);
  59.       super.allowAccumulate = false;
  60.    }
  61.  
  62.    public GifEncoder(ImageProducer var1, OutputStream var2, boolean var3) throws IOException {
  63.       super(var1, var2);
  64.       this.interlace = var3;
  65.       super.allowAccumulate = false;
  66.    }
  67.  
  68.    void encodeStart(int var1, int var2) throws IOException {
  69.       this.width = var1;
  70.       this.height = var2;
  71.       this.rgbPixels = new byte[var2][var1];
  72.    }
  73.  
  74.    private byte hashColor(int var1) {
  75.       int var2 = (var1 & 16777215) % 509;
  76.       GifEncoderHashitem var3 = this.hashArray[var2];
  77.       if (var3 == null || var3.rgb != var1) {
  78.          for(; var3 != null && var3.rgb != var1; var3 = this.hashArray[var2]) {
  79.             ++var2;
  80.             if (var2 == 509) {
  81.                var2 = 0;
  82.             }
  83.          }
  84.  
  85.          if (var3 == null) {
  86.             var3 = new GifEncoderHashitem(var1, 0, this.colorsUsed++, false);
  87.             this.hashArray[var2] = var3;
  88.          }
  89.       }
  90.  
  91.       ++var3.count;
  92.       return (byte)var3.index;
  93.    }
  94.  
  95.    void encodePixels(int var1, int var2, int var3, int var4, int[] var5, int var6, int var7) {
  96.       for(int var8 = 0; var8 < var4; ++var8) {
  97.          for(int var9 = 0; var9 < var3; ++var9) {
  98.             this.rgbPixels[var2 + var8][var1 + var9] = this.hashColor(var5[var8 * var7 + var6 + var9]);
  99.          }
  100.       }
  101.  
  102.    }
  103.  
  104.    void encodeDone() throws IOException {
  105.       if (this.colorsUsed >= 256) {
  106.          throw new IOException("too many colors for a GIF");
  107.       } else {
  108.          byte var1;
  109.          if (this.colorsUsed <= 2) {
  110.             var1 = 1;
  111.          } else if (this.colorsUsed <= 4) {
  112.             var1 = 2;
  113.          } else if (this.colorsUsed <= 16) {
  114.             var1 = 4;
  115.          } else {
  116.             var1 = 8;
  117.          }
  118.  
  119.          int var2 = 1 << var1;
  120.          byte[] var3 = new byte[var2];
  121.          byte[] var4 = new byte[var2];
  122.          byte[] var5 = new byte[var2];
  123.  
  124.          for(int var6 = 0; var6 < 509; ++var6) {
  125.             GifEncoderHashitem var7 = this.hashArray[var6];
  126.             if (var7 != null) {
  127.                var3[var7.index] = (byte)(var7.rgb >> 16 & 255);
  128.                var4[var7.index] = (byte)(var7.rgb >> 8 & 255);
  129.                var5[var7.index] = (byte)(var7.rgb & 255);
  130.             }
  131.          }
  132.  
  133.          this.GIFEncode(super.out, this.width, this.height, this.interlace, (byte)0, -1, var1, var3, var4, var5);
  134.       }
  135.    }
  136.  
  137.    byte GetPixel(int var1, int var2) {
  138.       return this.rgbPixels[var2][var1];
  139.    }
  140.  
  141.    static void writeString(OutputStream var0, String var1) throws IOException {
  142.       byte[] var2 = var1.getBytes();
  143.       var0.write(var2);
  144.    }
  145.  
  146.    void GIFEncode(OutputStream var1, int var2, int var3, boolean var4, byte var5, int var6, int var7, byte[] var8, byte[] var9, byte[] var10) throws IOException {
  147.       this.Width = var2;
  148.       this.Height = var3;
  149.       this.Interlace = var4;
  150.       int var14 = 1 << var7;
  151.       byte var13 = 0;
  152.       byte var12 = 0;
  153.       this.CountDown = var2 * var3;
  154.       this.Pass = 0;
  155.       int var15;
  156.       if (var7 <= 1) {
  157.          var15 = 2;
  158.       } else {
  159.          var15 = var7;
  160.       }
  161.  
  162.       this.curx = 0;
  163.       this.cury = 0;
  164.       writeString(var1, "GIF89a");
  165.       this.Putword(var2, var1);
  166.       this.Putword(var3, var1);
  167.       byte var11 = -128;
  168.       var11 = (byte)(var11 | 112);
  169.       var11 = (byte)(var11 | (byte)(var7 - 1));
  170.       this.Putbyte(var11, var1);
  171.       this.Putbyte(var5, var1);
  172.       this.Putbyte((byte)0, var1);
  173.  
  174.       for(int var16 = 0; var16 < var14; ++var16) {
  175.          this.Putbyte(var8[var16], var1);
  176.          this.Putbyte(var9[var16], var1);
  177.          this.Putbyte(var10[var16], var1);
  178.       }
  179.  
  180.       if (var6 != -1) {
  181.          this.Putbyte((byte)33, var1);
  182.          this.Putbyte((byte)-7, var1);
  183.          this.Putbyte((byte)4, var1);
  184.          this.Putbyte((byte)1, var1);
  185.          this.Putbyte((byte)0, var1);
  186.          this.Putbyte((byte)0, var1);
  187.          this.Putbyte((byte)var6, var1);
  188.          this.Putbyte((byte)0, var1);
  189.       }
  190.  
  191.       this.Putbyte((byte)44, var1);
  192.       this.Putword(var12, var1);
  193.       this.Putword(var13, var1);
  194.       this.Putword(var2, var1);
  195.       this.Putword(var3, var1);
  196.       if (var4) {
  197.          this.Putbyte((byte)64, var1);
  198.       } else {
  199.          this.Putbyte((byte)0, var1);
  200.       }
  201.  
  202.       this.Putbyte((byte)var15, var1);
  203.       this.compress(var15 + 1, var1);
  204.       this.Putbyte((byte)0, var1);
  205.       this.Putbyte((byte)59, var1);
  206.    }
  207.  
  208.    void BumpPixel() {
  209.       ++this.curx;
  210.       if (this.curx == this.Width) {
  211.          this.curx = 0;
  212.          if (!this.Interlace) {
  213.             ++this.cury;
  214.          } else {
  215.             switch (this.Pass) {
  216.                case 0:
  217.                   this.cury += 8;
  218.                   if (this.cury >= this.Height) {
  219.                      ++this.Pass;
  220.                      this.cury = 4;
  221.                   }
  222.                   break;
  223.                case 1:
  224.                   this.cury += 8;
  225.                   if (this.cury >= this.Height) {
  226.                      ++this.Pass;
  227.                      this.cury = 2;
  228.                   }
  229.                   break;
  230.                case 2:
  231.                   this.cury += 4;
  232.                   if (this.cury >= this.Height) {
  233.                      ++this.Pass;
  234.                      this.cury = 1;
  235.                   }
  236.                   break;
  237.                case 3:
  238.                   this.cury += 2;
  239.             }
  240.          }
  241.       }
  242.  
  243.    }
  244.  
  245.    int GIFNextPixel() throws IOException {
  246.       if (this.CountDown == 0) {
  247.          return -1;
  248.       } else {
  249.          --this.CountDown;
  250.          byte var1 = this.GetPixel(this.curx, this.cury);
  251.          this.BumpPixel();
  252.          return var1 & 255;
  253.       }
  254.    }
  255.  
  256.    void Putword(int var1, OutputStream var2) throws IOException {
  257.       this.Putbyte((byte)(var1 & 255), var2);
  258.       this.Putbyte((byte)(var1 >> 8 & 255), var2);
  259.    }
  260.  
  261.    void Putbyte(byte var1, OutputStream var2) throws IOException {
  262.       var2.write(var1);
  263.    }
  264.  
  265.    final int MAXCODE(int var1) {
  266.       return (1 << var1) - 1;
  267.    }
  268.  
  269.    void compress(int var1, OutputStream var2) throws IOException {
  270.       this.g_init_bits = var1;
  271.       this.clear_flg = false;
  272.       this.n_bits = this.g_init_bits;
  273.       this.maxcode = this.MAXCODE(this.n_bits);
  274.       this.ClearCode = 1 << var1 - 1;
  275.       this.EOFCode = this.ClearCode + 1;
  276.       this.free_ent = this.ClearCode + 2;
  277.       this.char_init();
  278.       int var6 = this.GIFNextPixel();
  279.       int var9 = 0;
  280.  
  281.       for(int var3 = this.hsize; var3 < 65536; var3 *= 2) {
  282.          ++var9;
  283.       }
  284.  
  285.       var9 = 8 - var9;
  286.       int var8 = this.hsize;
  287.       this.cl_hash(var8);
  288.       this.output(this.ClearCode, var2);
  289.  
  290.       int var5;
  291.       label43:
  292.       while((var5 = this.GIFNextPixel()) != -1) {
  293.          int var10 = (var5 << this.maxbits) + var6;
  294.          int var4 = var5 << var9 ^ var6;
  295.          if (this.htab[var4] == var10) {
  296.             var6 = this.codetab[var4];
  297.          } else {
  298.             if (this.htab[var4] >= 0) {
  299.                int var7 = var8 - var4;
  300.                if (var4 == 0) {
  301.                   var7 = 1;
  302.                }
  303.  
  304.                do {
  305.                   if ((var4 -= var7) < 0) {
  306.                      var4 += var8;
  307.                   }
  308.  
  309.                   if (this.htab[var4] == var10) {
  310.                      var6 = this.codetab[var4];
  311.                      continue label43;
  312.                   }
  313.                } while(this.htab[var4] >= 0);
  314.             }
  315.  
  316.             this.output(var6, var2);
  317.             var6 = var5;
  318.             if (this.free_ent < this.maxmaxcode) {
  319.                this.codetab[var4] = this.free_ent++;
  320.                this.htab[var4] = var10;
  321.             } else {
  322.                this.cl_block(var2);
  323.             }
  324.          }
  325.       }
  326.  
  327.       this.output(var6, var2);
  328.       this.output(this.EOFCode, var2);
  329.    }
  330.  
  331.    void output(int var1, OutputStream var2) throws IOException {
  332.       this.cur_accum &= this.masks[this.cur_bits];
  333.       if (this.cur_bits > 0) {
  334.          this.cur_accum |= var1 << this.cur_bits;
  335.       } else {
  336.          this.cur_accum = var1;
  337.       }
  338.  
  339.       for(this.cur_bits += this.n_bits; this.cur_bits >= 8; this.cur_bits -= 8) {
  340.          this.char_out((byte)(this.cur_accum & 255), var2);
  341.          this.cur_accum >>= 8;
  342.       }
  343.  
  344.       if (this.free_ent > this.maxcode || this.clear_flg) {
  345.          if (this.clear_flg) {
  346.             this.maxcode = this.MAXCODE(this.n_bits = this.g_init_bits);
  347.             this.clear_flg = false;
  348.          } else {
  349.             ++this.n_bits;
  350.             if (this.n_bits == this.maxbits) {
  351.                this.maxcode = this.maxmaxcode;
  352.             } else {
  353.                this.maxcode = this.MAXCODE(this.n_bits);
  354.             }
  355.          }
  356.       }
  357.  
  358.       if (var1 == this.EOFCode) {
  359.          while(this.cur_bits > 0) {
  360.             this.char_out((byte)(this.cur_accum & 255), var2);
  361.             this.cur_accum >>= 8;
  362.             this.cur_bits -= 8;
  363.          }
  364.  
  365.          this.flush_char(var2);
  366.       }
  367.  
  368.    }
  369.  
  370.    void cl_block(OutputStream var1) throws IOException {
  371.       this.cl_hash(this.hsize);
  372.       this.free_ent = this.ClearCode + 2;
  373.       this.clear_flg = true;
  374.       this.output(this.ClearCode, var1);
  375.    }
  376.  
  377.    void cl_hash(int var1) {
  378.       for(int var2 = 0; var2 < var1; ++var2) {
  379.          this.htab[var2] = -1;
  380.       }
  381.  
  382.    }
  383.  
  384.    void char_init() {
  385.       this.a_count = 0;
  386.    }
  387.  
  388.    void char_out(byte var1, OutputStream var2) throws IOException {
  389.       this.accum[this.a_count++] = var1;
  390.       if (this.a_count >= 254) {
  391.          this.flush_char(var2);
  392.       }
  393.  
  394.    }
  395.  
  396.    void flush_char(OutputStream var1) throws IOException {
  397.       if (this.a_count > 0) {
  398.          var1.write(this.a_count);
  399.          var1.write(this.accum, 0, this.a_count);
  400.          this.a_count = 0;
  401.       }
  402.  
  403.    }
  404. }
  405.